import { useCallback, useState, useReducer } from "react";

type State<T> = {
  past: T[];
  future: T[];
  present: T;
};

const UNDO = "UNDO";
const REDO = "REDO";
const SET = "SET";
const RESET = "RESET";

type Action<T> = {
  newPresent?: T;
  type: typeof UNDO | typeof REDO | typeof SET | typeof RESET;
};
const undoReducer = <T>(state: State<T>, action: Action<T>) => {
  const { past, present, future } = state;
  const { newPresent, type } = action;
  switch (type) {
    case UNDO: {
      if (past.length === 0) return state;
      const previous = past[past.length - 1];
      const newPast = past.slice(0, past.length - 1); //从第0个起，倒数第二个结束，复制到新的数组
      return {
        past: newPast,
        future: [present, ...future],
        present: previous,
      };
    }
    case REDO: {
      if (future.length === 0) return state;
      const next = future[0];
      const newFuture = future.slice(1);
      return { past: [present, ...past], future: newFuture, present: next };
    }
    case SET: {
        if (newPresent === present) return state;
      return { past: [...past, present], present: newPresent, future: [] };
    }
    case RESET: {
        if (newPresent === present) return state;
      return { past: [], present: newPresent, future: [] };
    }
  }
  return state;
};

export const useUndo = <T>(initialPresent: T) => {
  const [state, dispatch] = useReducer(undoReducer, {
    past: [],
    future: [],
    present: initialPresent,
  } as State<T>);

  //队列由 过去队列 + 现在 + 未来队列 组成
  const canUndo = state.past.length !== 0;
  const canRedo = state.future.length !== 0;
  const undo = useCallback(() => dispatch({type: UNDO}), []); //函数中没有用到任何state,不需要依赖
  const redo = useCallback(() => dispatch({type: REDO}), []);
  const set = useCallback((newPresent: T) => dispatch({type: SET, newPresent: newPresent}), []);
  const reset = useCallback((newPresent: T) => dispatch({type: RESET, newPresent: newPresent}), []);

  return [state, { undo, redo, set, reset, canRedo, canUndo }] as const;
};
